﻿using System;
using System.Net;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Documents;
using System.Windows.Ink;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Shapes;
using Payton.WP7.Common.Model;
using System.Collections.Generic;
using System.IO.IsolatedStorage;
using System.Linq;
using Payton.WP7.Common.Interface;

namespace Payton.WP7.Common
{
    public class AccountManager : IAccountManager
    {
        private const string AccountSettings = "AccountSettings";

        Dictionary<int, SNSAccount> _accounts = new Dictionary<int, SNSAccount>();

        public event EventHandler<CreateNewAccountEventArgs> OnCreateNewAccount;

        public event EventHandler<AccountRemovedEventArgs> OnAccountRemoved;

        AccountManager()
        {

        }

        static AccountManager _currrent;
        public static AccountManager Current
        {
            get
            {
                if (_currrent == null)
                    _currrent = new AccountManager();
                return _currrent;
            }
        }

        public SNSAccount CreateAccount(SNSProviderType providType)
        {
            lock (_accounts)
            {
                int id = 0;
                if (_accounts.Count > 0)
                    id = _accounts.Max(a => a.Key) + 1;
                var account = new SNSAccount(providType, id);
                _accounts.Add(account.AccountID, account);

                account.PropertyChanged += new System.ComponentModel.PropertyChangedEventHandler(account_PropertyChanged);

                return account;
            }
        }

        void account_PropertyChanged(object sender, System.ComponentModel.PropertyChangedEventArgs e)
        {
            var account = sender as SNSAccount;
            if (account == null)
                return;

            switch (e.PropertyName)
            {
                case "IsBind":
                    if (account.IsBind)
                    {
                        if (OnCreateNewAccount != null)
                            OnCreateNewAccount(this, new CreateNewAccountEventArgs() { NewAccount = account });
                    }
                    break;
                case "IsDestination":
                    if (account.IsDestination)
                    {
                        if (account.ServiceProvider == SNSProviderType.Sina && _accounts.Any(a => a.Value.ServiceProvider != SNSProviderType.Sina))
                        {
                            var accounts = _accounts.Where(a => a.Value.ServiceProvider != SNSProviderType.Sina);
                            foreach (var other in accounts)
                            {
                                if (other.Value.IsDestination)
                                    other.Value.IsDestination = false;
                            }
                        }
                        else if (account.ServiceProvider != SNSProviderType.Sina && _accounts.Any(a => a.Value.ServiceProvider == SNSProviderType.Sina))
                        {
                            var sinaaccounts = _accounts.Where(a => a.Value.ServiceProvider == SNSProviderType.Sina);
                            foreach (var sina in sinaaccounts)
                            {
                                if (sina.Value.IsDestination)
                                    sina.Value.IsDestination = false;
                            }
                        }
                    }
                    break;
                default:
                    break;
            }
        }

        public SNSAccount GetAccount(int accountID)
        {
            return _accounts[accountID];
        }

        public IEnumerable<SNSAccount> GetAllAccount()
        {
            var list = new List<SNSAccount>();

            foreach (var account in _accounts)
            {
                list.Add(account.Value);
            }
            return list;
        }

        public bool ContainsAccount(int id)
        {
            return _accounts.ContainsKey(id);
        }

        public int Count
        {
            get { return _accounts.Count; }
        }



        public void Load()
        {

#if WINDOWS_PHONE
            if (Microsoft.Phone.Shell.PhoneApplicationService.Current.State.ContainsKey(AccountSettings))
            {
                _accounts = Microsoft.Phone.Shell.PhoneApplicationService.Current.State[AccountSettings] as Dictionary<int, SNSAccount>;
                goto LABEL_ADD_ENVENTHANDLE;
            }
#endif

            if (IsolatedStorageSettings.ApplicationSettings.Contains(AccountSettings))
            {
                _accounts = IsolatedStorageSettings.ApplicationSettings[AccountSettings] as Dictionary<int, SNSAccount>;
#if WINDOWS_PHONE
                if (!Microsoft.Phone.Shell.PhoneApplicationService.Current.State.ContainsKey(AccountSettings))
                    Microsoft.Phone.Shell.PhoneApplicationService.Current.State.Add(AccountSettings, _accounts);
                else
                    Microsoft.Phone.Shell.PhoneApplicationService.Current.State[AccountSettings] = _accounts;
#endif

                //AccountManager.Current.SetAccountList(AccountList);
            }

        LABEL_ADD_ENVENTHANDLE:
            foreach (var account in _accounts.Where(a => a.Value.IsBind == true))
            {
                account.Value.PropertyChanged -= account_PropertyChanged;
                account.Value.PropertyChanged += account_PropertyChanged;
            }

        }

        public void Save()
        {
            //just save account who has been successfully binded
            var _dic = new Dictionary<int, SNSAccount>();
            foreach (var e in _accounts)
            {
                if (e.Value.IsBind)
                {
                    _dic.Add(e.Key, e.Value);
                }
            }
            IsolatedStorageSettings.ApplicationSettings[AccountSettings] = _dic;
        }

        public void RemoveAccount(SNSAccount account)
        {
            if (_accounts.ContainsKey(account.AccountID))
            {
                _accounts.Remove(account.AccountID);
                if (OnAccountRemoved != null)
                    OnAccountRemoved(this, new AccountRemovedEventArgs() { RemovedAccount = account });
            }
        }

        public void RemoveAccount(int accountid)
        {
            if (_accounts.ContainsKey(accountid))
            {
                var account = _accounts[accountid];
                _accounts.Remove(accountid);
                if (OnAccountRemoved != null)
                    OnAccountRemoved(this, new AccountRemovedEventArgs() { RemovedAccount = account });
            }
        }

        public void Remove(Func<SNSAccount, bool> filter)
        {
            lock (_accounts)
            {
                List<int> removeItems = new List<int>();
                foreach (var account in _accounts)
                {
                    if (filter(account.Value))
                    {
                        removeItems.Add(account.Key);
                    }
                }
                foreach (int id in removeItems)
                {
                    RemoveAccount(id);
                }
            }

        }
    }
}
